﻿using System;
using System.ComponentModel;
using System.ServiceModel.DomainServices.Client;

using Warehouse.Silverlight.Core.Infrastructure.Events;

namespace Warehouse.Silverlight.Core.Infrastructure.Models
{
    public class Model<T> : Model where T : DomainContext
    {
        private T _context;

        public Model()
        {
            this.Initialize();

            _context.PropertyChanged += new PropertyChangedEventHandler(_context_PropertyChanged);
        }

        protected override void Initialize()
        {
            
        }

        protected T Context
        {
            get { return _context; }
            set
            {
                if (_context != value)
                {
                    _context = value;
                    RaisePropertyChanged(() => Context);
                }
            }
        }

        public event EventHandler<SubmitOperationEventArgs> SubmitChangesComplete;
        public virtual void SubmitChangesAsync()
        {
            this.Context.SubmitChanges(s =>
            {
                if (SubmitChangesComplete != null)
                {
                    try
                    {
                        Exception ex = null;
                        if (s.HasError)
                        {
                            ex = s.Error;
                            s.MarkErrorAsHandled();
                        }
                        SubmitChangesComplete(this, new SubmitOperationEventArgs(s, ex));
                    }
                    catch (Exception ex)
                    {
                        SubmitChangesComplete(this, new SubmitOperationEventArgs(ex));
                    }
                }
            }, null);
        }

        public virtual void RejectChanges()
        {
            this.Context.RejectChanges();
        }

        protected virtual void _context_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "HasChanges":
                    this.HasChanges = _context.HasChanges;
                    break;
                case "IsLoading":
                    this.IsBusy = _context.IsLoading;
                    break;
                case "IsSubmitting":
                    this.IsBusy = _context.IsSubmitting;
                    break;
            }
        }

        protected void PerformEntityQuery<TEntity>(EntityQuery<TEntity> query, EventHandler<EntityResultsArgs<TEntity>> handler) where TEntity : Entity
        {
            Context.Load<TEntity>(query, LoadBehavior.RefreshCurrent, r =>
            {
                if (handler != null)
                {
                    try
                    {
                        if (r.HasError)
                        {
                            handler(this, new EntityResultsArgs<TEntity>(r.Error));
                            r.MarkErrorAsHandled();
                        }
                        else
                        {
                            handler(this, new EntityResultsArgs<TEntity>(r.Entities));
                        }
                    }
                    catch (Exception ex)
                    {
                        handler(this, new EntityResultsArgs<TEntity>(ex));
                    }
                }
            }, null);
        }
    }
}
